/*
Java board game library.
Copyright (C) 2011  Deepesh Garg

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

package d.g.boardgames.chess;

import d.g.boardgames.BoardSerializer;
import d.g.boardgames.chess.ChessCellState.PieceColor;
import d.g.boardgames.chess.ChessCellState.PieceType;

public class FENSerializer implements BoardSerializer<ChessBoard> {

	public ChessBoard getBoard(String str) {
		try {
			ChessBoard board = new ChessBoard(true);

			int index = 0 ;
			int len = str.length() ;

			for (int row = 0; row < 8; row++) {
				char c = str.charAt(index++) ;
				int col = 0 ;
				while (c != '/' && col < 8) {
					if (c == ' ') {
						break;
					}
					int skip = 1 ;
					if (c == 'p') {
						board.setCellState(row, col,ChessCellState.BLACK_PAWN) ;
					} else if (c == 'P') {
						board.setCellState(row, col, ChessCellState.WHITE_PAWN) ;
					} else if (c == 'r') {
						board.setCellState(row, col, ChessCellState.BLACK_ROOK) ;
					} else if (c == 'R') {
						board.setCellState(row, col, ChessCellState.WHITE_ROOK) ;
					} else if (c == 'n') {
						board.setCellState(row, col, ChessCellState.BLACK_KNIGHT) ;
					} else if (c == 'N') {
						board.setCellState(row, col, ChessCellState.WHITE_KNIGHT) ;
					} else if (c == 'b') {
						board.setCellState(row, col, ChessCellState.BLACK_BISHOP) ;
					} else if (c == 'B') {
						board.setCellState(row, col, ChessCellState.WHITE_BISHOP) ;
					} else if (c == 'q') {
						board.setCellState(row, col, ChessCellState.BLACK_QUEEN) ;
					} else if (c == 'Q') {
						board.setCellState(row, col, ChessCellState.WHITE_QUEEN) ;
					} else if (c == 'k') {
						board.setCellState(row, col, ChessCellState.BLACK_KING) ;
					} else if (c == 'K') {
						board.setCellState(row, col, ChessCellState.WHITE_KING) ;
					} else {
						try {
							skip = Integer.parseInt ("" + c) ;
						} catch (NumberFormatException nfe) {
						}
					}
					c = str.charAt(index++) ;
					col+= skip ;
				}
			}
			while (index < str.length() && (str.charAt(index) == ' ' || str.charAt(index) == '\t')) {
				index++;
			}
			if (str.charAt(index) == 'w' || str.charAt(index) == 'W') {
				board.turn = PieceColor.WHITE;
			}
			if (str.charAt(index) == 'b' || str.charAt(index) == 'B') {
				board.turn = PieceColor.BLACK;
			}
			index++;
			while (index < str.length() && (str.charAt(index) == ' ' || str.charAt(index) == '\t')) {
				index++;
			}
			boolean castelingStatusSet = false;
			while (!castelingStatusSet && index < str.length()) {
				if (str.charAt(index) == 'k') {
					board.blackKingSideCastleAllowed = true;
				}
				if (str.charAt(index) == 'q') {
					board.blackQueenSideCastleAllowed = true;
				}
				if (str.charAt(index) == 'K') {
					board.whiteKingSideCastleAllowed = true;
				}
				if (str.charAt(index) == 'Q') {
					board.whiteQueenSideCastleAllowed = true;
				}
				if (str.charAt(index) == '-' || str.charAt(index) == ' ' || str.charAt(index) == '\t') {
					castelingStatusSet = true;
				}
				index++;
			}
			while (index < str.length() && (str.charAt(index) == ' ' || str.charAt(index) == '\t')) {
				index++;
			}
			if (index < str.length() && str.charAt(index) != '-') {
				if (board.turn == PieceColor.WHITE) {
					board.passedPawn = AlgebricNotationHelper.getCell(str.charAt(index) + "3");
				} else if (board.turn == PieceColor.BLACK) {
					board.passedPawn = AlgebricNotationHelper.getCell(str.charAt(index) + "6");
				}
			}
			return board;
		} catch (Throwable e) {
			e.printStackTrace();
			return null;
		}
	}

	public String getString(ChessBoard board) {
		String fenString = "";
		for (int row = 0; row < 8; row++) {
			int skip = 0;
			for (int col = 0; col < 8; col++) {
				ChessCellState cellState = board.getCellState(row, col);
				if (cellState == null) {
					skip++;
				} else {
					fenString += skip != 0? skip : "";
					skip = 0;
					String pieceStr = "";
					switch (cellState.pieceType) {
						case PAWN : pieceStr = "p"; break;
						case KNIGHT : pieceStr = "n"; break;
						case BISHOP : pieceStr = "b"; break;
						case ROOK : pieceStr = "r"; break;
						case QUEEN : pieceStr = "q"; break;
						case KING  : pieceStr = "k";break;
					}
					if (cellState.pieceColor == PieceColor.WHITE) {
						pieceStr = pieceStr.toUpperCase();
					}
					fenString += pieceStr;
				}
			}
			if (row != 7) {
				fenString += "/";
			}
		}
		if (board.getTurn() == PieceColor.WHITE) {
			fenString += " w";
		} else {
			fenString += " b";
		}
		String castelingStatus = "" ;
		if (board.isWhiteKingSideCastleAllowed()) {
			castelingStatus += "K";
		}
		if (board.isWhiteQueenSideCastleAllowed()) {
			castelingStatus += "Q";
		}
		if (board.isBlackKingSideCastleAllowed()) {
			castelingStatus += "k";
		}
		if (board.isBlackQueenSideCastleAllowed()) {
			castelingStatus += "q";
		}
		fenString += castelingStatus.equals("")? " -" : (" " + castelingStatus);
		
		if (board.passedPawn != null) {
			fenString += " " + AlgebricNotationHelper.getCellString(board.passedPawn);
		} else {
			fenString += " -";
		}
		return fenString;
	}
	
}
